use egui::IconData;
use image::GenericImageView;
mod graph;
mod data;
mod app;
mod exporter;

use std::fs;
use std::path::PathBuf;

#[cfg(not(feature = "exporter"))]
fn main() {
    let mut viewport = egui::ViewportBuilder::default()
        .with_min_inner_size([1366.0, 768.0])
        .with_maximized(true);
    
    // 获取资源路径
    let mut resource_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    resource_dir.push("resources");
    let icon_path = resource_dir.join("app.ico");

    // 检查图标文件是否存在并加载
    if icon_path.exists() {
        match fs::read(&icon_path) {
            Ok(bytes) => {
                if let Ok(dynimage) = image::load_from_memory(&bytes) {
                    let (width, height) = dynimage.dimensions();
                    viewport = viewport.with_icon(IconData {
                        rgba: dynimage.into_bytes(),
                        width: width,
                        height: height,
                    });
                } else {
                    eprintln!("无法从内存加载图标图像");
                }
            }
            Err(e) => eprintln!("读取图标文件失败: {:?}", e),
        }
    } else {
        eprintln!("图标文件不存在: {:?}", icon_path);
    }

    let native_options = eframe::NativeOptions {
        viewport,
        ..Default::default()
    };

    eframe::run_native(
        "behavior editor",
        native_options,
        Box::new(|ctx| {
            let font_path = resource_dir.join("font.ttf");
            if font_path.exists() {
                match fs::read(&font_path) {
                    Ok(bytes) => {
                        let mut fonts = egui::FontDefinitions::default();
                        fonts.font_data.insert("custom_font".to_owned(), egui::FontData::from_owned(bytes));
                        fonts.families.get_mut(&eframe::egui::FontFamily::Proportional).unwrap().insert(0, "custom_font".to_owned());
                        fonts.families.get_mut(&eframe::egui::FontFamily::Monospace).unwrap().insert(0, "custom_font".to_owned());
                        ctx.egui_ctx.set_fonts(fonts);
                    }
                    Err(e) => eprintln!("读取字体文件失败: {:?}", e),
                }
            }

            let mut app = app::App::new();
            app.set_graph_data(gen_graph_data());
            Ok(Box::new(app))
        }),
    )
    .expect("运行本地程序失败");
}

fn gen_graph_data() -> data::GraphData {
    data::GraphData {
        nodes: vec![
            data::NodeData{ 
                name: "node1".to_string(),
                ty: "node1".to_string(),
                description: Some("node1 description".to_string()),
                inputs: vec![
                    data::InputData {
                        name: "in i32".to_string(),
                        description: Some("input1 description".to_string()),
                        value: graph::value::Value::I32(1)
                    },
                    data::InputData {
                        name: "in f32".to_string(),
                        description: Some("input2 description".to_string()),
                        value: graph::value::Value::F32(1.0)
                    },
                    data::InputData {
                        name: "in str".to_string(),
                        description: Some("input3 description".to_string()),
                        value: graph::value::Value::String("".to_string())
                    }
                ],
                outputs: vec![
                    data::OutputData {
                        name: "out i32".to_string(),
                        description: Some("output1 description".to_string()),
                        value: graph::value::Value::I32(1)
                    },
                    data::OutputData {
                        name: "out f32".to_string(),
                        description: Some("output2 description".to_string()),
                        value: graph::value::Value::F32(1.0)
                    },
                    data::OutputData {
                        name: "out str".to_string(),
                        description: Some("output3 description".to_string()),
                        value: graph::value::Value::String("".to_string())
                    }
                ],
                children_count: None,
                menu: Some("a/b/c".to_string()),
                has_children: true,
            },
            data::NodeData{ 
                name: "node2".to_string(),
                ty: "node2".to_string(),
                description: Some("node2 description".to_string()),
                inputs: vec![
                    data::InputData {
                        name: "in i32".to_string(),
                        description: Some("input1 description".to_string()),
                        value: graph::value::Value::I32(1)
                    },
                    data::InputData {
                        name: "in f32".to_string(),
                        description: Some("input2 description".to_string()),
                        value: graph::value::Value::F32(1.0)
                    },
                    data::InputData {
                        name: "in str".to_string(),
                        description: Some("input3 description".to_string()),
                        value: graph::value::Value::String("".to_string())
                    }
                ],
                outputs: vec![
                    data::OutputData {
                        name: "out i32".to_string(),
                        description: Some("output1 description".to_string()),
                        value: graph::value::Value::I32(1)
                    },
                    data::OutputData {
                        name: "out f32".to_string(),
                        description: Some("output2 description".to_string()),
                        value: graph::value::Value::F32(1.0)
                    },
                    data::OutputData {
                        name: "out str".to_string(),
                        description: Some("output3 description".to_string()),
                        value: graph::value::Value::String("".to_string())
                    }
                ],
                children_count: None,
                menu: Some("a/c/d".to_string()),
                has_children: true,
            }
        ]
    }
}
